package com.barradata.app0624.api

import android.location.Location
import com.barradata.BuildConfig
import com.barradata.app0624.config.Constant
import com.barradata.app0624.data.UserDataManager
import com.barradata.app0624.model.FbLoginData
import com.example.hfiveandaplication.bean.*
import com.example.hfiveandaplication.http.RetrofitManager
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.FormBody
import okhttp3.MultipartBody
import java.io.File
import java.util.*


/**
 * Author:    WuNan
 * Email:     wunan@barradata.com
 * Created:   2019/7/4 19:45
 **/

object ApiService {
    enum class UploadImageType {
        @Deprecated("后台接口规定此参数为从 1 开始，_NONE 只作为占位符使用")
        _NONE,                  // 占位符 0
        ID_CARD,                // 身份证照片 1
        ID_CARD_WITH_PORTRAIT,  // 手持身份证照片 2
        TAX,                    // 税单照片 3
        INSURANCE_ORDER,        // 保险单照片 4
        HOUSEHOLD_REGISTER,     // 户口本照片 5
        PASSBOOK,               // 存折 6
        BUSINESS_CARD,          // 名片 7
        DRIVE_CARD,             // 驾照 8
        CAR_NO,                 // 车牌号 9
        LOAN_USAGE,             // 借款用途凭证 10
        CREDIT_CARD,            // 信用卡照片 11
        WORK_CARD,              // 工作证明 12
        BANK_CARD,              // 银行卡照片 13

    }

    enum class DictionaryType {
        COMMON_PROFESSIONAL, // 工作类型    工作认证使用的
        CURRENT_POSITION,    // 当前职位    工作认证使用的
        SALARY_TREATMENT,    // 薪资范围    工作认证使用的
        NEED_MONEY,          // 借款金额    借款需求认证
        USAGE_OF_LOAN,       // 借款用途    借款需求认证
        COMMON_EDUCATION,    // 学历       个人信息认证
        NUMBER_OF_CHILDREN,  // 子女数量    个人信息认证
        NUMBER_OF_FAMILY_MEMBERS, //  家庭成员数  个人信息认证
        COMMON_HOMEOWNER,    // 住房类别    个人信息认证
        RENTAL_SCOPE,        // 租金范围    个人信息认证
        COMMON_RELATION,     // 联系人关系类型   联系人认证
        COMMON_BANKNAME      // 开户银行         银行卡认证的
    }

    enum class AuthPageCode {
        IDENTITY_CODE,        // 身份证认证
        COMPANY_CODE,         // 工作信息认证
        BORROWING_NEEDS_CODE, // 借款认证
        PERSONAGE_INFO_CODE,  // 个人信息认证
        CONTACTS_CODE,        // 联系人认证
        BANK_INFO_CODE,       // 银行卡认证
        ADDITIONAL_INFORMATION_CODE //补充信息认证
    }

    private val netService = RetrofitManager.getInstance().iNetService

    /**
     * 为 com.example.hfiveandaplication.http.Api 接口内定义的函数添加线程切换扩展，从而将调用方式由参数式改为内联式
     *
     * 线程切换：
     *  - subscribeOn 事件发生时再此线程内进行处理
     *  - observeOn   事件经流式处理后将最终结果交由该线程处理，即最终的 onNext、onError、onCompleted 函数回调均在此线程执行
     *
     * 原调用方式： netService.login(params.toJsonParam()).compose(applySchedulers())
     *
     * 现调用方式： netService.login(params.toJsonParam()).composeSchedulers()
     */
    private fun <T> Observable<BaseResponse<T>>.composeSchedulers(): Observable<BaseResponse<T>> {
        return this.compose {
            it.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
        }
    }

    fun login(username: String, password: String): Observable<BaseResponse<LoginData>> {
        val params = Params()
        params.putUserName(username)
        params.putPassword(password)
        return netService.login(params.toJsonParam()).composeSchedulers()
    }

    fun getStatus(): Observable<BaseResponse<AuthData>> {
        return netService.getAuthStatus(UserDataManager.token, Params().toJsonParam()).composeSchedulers()
    }

    fun uploadImage(uploadImageType: UploadImageType, file: File): Observable<BaseResponse<IdentityData>> {
        val params = Params()
        params.putFileType(uploadImageType.ordinal.toString())
        params.putUserUuid(UserDataManager.uuid)
        val requestBody = FormBody.create(MultipartBody.FORM, file.readBytes())
        val multipart = MultipartBody.Part.createFormData("file", "file", requestBody)
        return netService.uploadIdentityCard(UserDataManager.token, params.toCommonParamStr(), multipart).composeSchedulers()
    }

    fun getDictionary(type: DictionaryType): Observable<BaseResponse<ArrayList<DictionaryItemData>>> {
        val params = Params()
        params.putDicType(type)
        return netService.getDictionaryData(Constant.CHANNEL, UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun uploadContactInfo(paramList: Any): Observable<BaseResponse<String>> {
        val params = Params()
        params.putUserUuid(UserDataManager.uuid)
        params.put("paramList", paramList)
        params.putAuthPageCode(ApiService.AuthPageCode.CONTACTS_CODE)
        return netService.uploadContactData(UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun imageCompare(firstImagePath: String, secondImagePath: String): Observable<BaseResponse<CompareData>> {
        val params = Params()
        params.putUserUuid(UserDataManager.uuid)
        params.put("firstImagePath", firstImagePath)
        params.put("secondImagePath", secondImagePath)
        return netService.imgCompare(UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun updateUserInfo(pass: Int, identityBean: IdentityData.IdentityBean, imageInfoList: List<IdentityData.ImageInfoBean>): Observable<BaseResponse<String>> {
        val params = Params()
        params.putAll(identityBean.toMap())
        params.putUserUuid(UserDataManager.uuid)
        params.putAuthPageCode(ApiService.AuthPageCode.IDENTITY_CODE)
        params.put("imageInfoParams", imageInfoList)
        params.put("pass", pass)
        return netService.saveIdentity(UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun updateAdditionalInfo(uploadImageInfoArr: List<IdentityData.ImageInfoBean>): Observable<BaseResponse<String>> {
        val params = Params()
        params.putUserUuid(UserDataManager.uuid)
        params.putAuthPageCode(ApiService.AuthPageCode.ADDITIONAL_INFORMATION_CODE)
        params.put("imageList", uploadImageInfoArr)
        return netService.saveAddInformation(UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun updateBankAuthInfo(realName: String, bankCode: String, bankName: String, bankCard: String): Observable<BaseResponse<String>> {
        val params = Params()
        params.putUserUuid(UserDataManager.uuid)
        params.putAuthPageCode(ApiService.AuthPageCode.BANK_INFO_CODE)
        params.put("realName", realName)
        params.put("bankCode", bankCode)
        params.put("bankName", bankName)
        params.put("bankCard", bankCard)
        return netService.saveBankCardInfo(UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun createOrder(pid: String, expiryReturned: String, addressBookUuid: String): Observable<BaseResponse<String>> {
        val params = Params()
        params.put("pId", pid)
        params.put("expiryReturned", expiryReturned)
        params.putUserUuid(UserDataManager.uuid)
        if (UserDataManager.addressBookUuid.isEmpty()) {
            params.putAddressBookUuid(addressBookUuid)
        }
        return netService.createOrder(Constant.CHANNEL, UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun uploadLocationInfo(location: Location): Observable<BaseResponse<String>> {
        val params = Params()
        params["longitude"] = location.longitude.toString()
        params["latitude"] = location.latitude.toString()
        params["saveType"] = "2"
        params["userPhone"] = ""
        params["userUuid"] = UserDataManager.uuid
        params["addressBookUuid"] = UserDataManager.addressBookUuid
        return netService.uploadLocationRegister(Constant.CHANNEL, UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun getGooglePlayUpdateInfo(): Observable<BaseResponse<UpdateData>> {
        val params = Params()
        return netService.getGooglePlayUpdateInfo(Constant.CHANNEL, UserDataManager.token, params.toJsonParam()).composeSchedulers()
    }

    fun facebookLogin(fbAuthCode: String): Observable<BaseResponse<FbLoginData>> {
        val params = Params()
        params["authCode"] = fbAuthCode
        return netService.faceBookLogin(Constant.CHANNEL, params.toJsonParam()).composeSchedulers()
    }

}